package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.admin.feign.ArticleFeign;
import com.heima.admin.feign.WemediaFeign;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.common.aliyun.GreeTextScan;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.constans.admin.AuthConstants;
import com.heima.common.constans.message.ArticleForEsConstants;
import com.heima.common.fastdfs.FastDFSClient;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.auth.AUTH;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;


@Service
@Log4j2
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    WemediaFeign wemediaFeign;
     @Autowired
     KafkaTemplate kafkaTemplate;
    @GlobalTransactional
    @Override
    public void autoScanByMediaNewsId(Integer id) {
        //检查id
        if(id==null){
            log.error("当前id为空");
            return;
        }
        //根据id查询自媒体文章信息
        WmNews wmNews = wemediaFeign.findById(id);
        if(wmNews==null){
            log.error("审核文章不存在，自媒体id：{}",id);
            return;
        }
        //文章状态为8或4 发布时间<=当前时间直接发布文章
        if((wmNews.getStatus()==4||(wmNews.getStatus()==8))&& wmNews.getPublishTime().getTime()<=System.currentTimeMillis()
        ){
            saveAppArticle(wmNews);
            return;
        }
        //文章状态为1.待审核，执行审核步骤
        if(wmNews.getStatus()==1){
            //4.1抽取出文章所包含的文本内容和图片内容
            //ket :text value:内容字符串 key:images value:图片url信息
            Map<String,Object> textAndImageList=handleTextAndImages(wmNews);
            //4.2阿里云文本反垃圾审核 review
            String text = (String)textAndImageList.get("text");
            if(StringUtils.isNotBlank(text)){
                //如果失败 直接将文章状态 修改为2 如果结束是review 修改为3待人工审核
                boolean textResult=handleTextScan(wmNews,text);
                if(!textResult) return;;
            }
            //4.3阿里云图片审核 pass blocked review
            List<String> images=(List<String>)textAndImageList.get("images");
            if(images!=null && !images.isEmpty()){
                boolean imgeResult=handleImagesScan(wmNews,images);
                if(!imgeResult) return;;
            }
            //4.4查询敏感词库，进行敏感词审核
            if(StringUtils.isNotBlank(text)){
                //如果失败 文章状态为2 如果结果是reviw  修改为3
                boolean sensitiveResult=handleSensitive(wmNews,text);
                //如果查询内容包含敏感词 改为2
                if(!sensitiveResult) return;
            }
            //4.5如果审核通过
           if(wmNews.getPublishTime().getTime()<=System.currentTimeMillis()){
                   //发布文章
               saveAppArticle(wmNews);
           }else {
              //将文章状态改为8 代表自动审核通过
               updateWmNews(wmNews,(short)8,"审核通过");
           }
           return;
        }
        //审核通过修改自媒体文章状态为9 保存app端相关文章信息
    }

    @Override
    public PageResponseResult findNews(NewsAuthDto dto) {
        //分页查询
        PageResponseResult responseResult = wemediaFeign.findList(dto);
        //有图片需要显示，需要fastdfs服务器地址
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }

    @Override
    public ResponseResult findOne(Integer id) {
        //检查参数
        if(id==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //查询数据
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        //结构封装
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }

    @Override
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        //参数检查
        if(dto==null || dto.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"用户不存在");
        }
        //查询文章
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        //审核没有通过
        if(wmNews==null){
            updateWmNews(wmNews,(short)2,dto.getMsg());
        }else if(type.equals(1)){
            //人工审核通过
            updateWmNews(wmNews,(short)4,"人工审核通过");
        }

        return ResponseResult.okResult();
    }

    //当前方法为发布方法
    private  void saveAppArticle(WmNews wmNews){
        //保存ap_Article表信息
        ApArticle apArticle =saveArticle(wmNews);
        wmNews.setArticleId(apArticle.getId());
        //保存ap_article_config配置表信息
        saveArticleConfig(apArticle);
        //保存ap_article_content
        saveArticleContent(apArticle,wmNews);
        //将文章状态改为9
        wmNews.setArticleId(apArticle.getId()); //关联app端文章id
        updateWmNews(wmNews,(short)9,"文章发布");
        //es索引创建
        kafkaTemplate.send(ArticleForEsConstants.ARTICLE_ELASTICSEARCH_ADD,apArticle.getId().toString());
    }
    @Autowired
    ArticleFeign articleFeign;
    @Autowired
    AdChannelMapper adChannelMapper;
   //app端文章添加
    private ApArticle saveArticle(WmNews wmNews) {
        //创建文章
        ApArticle apArticle = new ApArticle();
        apArticle.setTitle(wmNews.getTitle());
        apArticle.setFlag((byte)0);
        apArticle.setLayout(wmNews.getType());
        apArticle.setImages(wmNews.getImages());
        apArticle.setLabels(wmNews.getLabels());
        apArticle.setCreatedTime(new Date());
        apArticle.setPublishTime(wmNews.getPublishTime());
        Integer userId = wmNews.getUserId();
        //获取自媒体用户
        WmUser wmUser = wemediaFeign.findWmUserById(Long.valueOf(userId));
        //设置作者信息
        ApAuthor author = articleFeign.findAuthorByUserId(String.valueOf(wmUser.getApAuthorId()));
        if(author!=null){
            apArticle.setAuthorId(Long.valueOf(author.getId()));
            apArticle.setAuthorName(author.getName());
        }
        //设置频道信息
        AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());
        if(adChannel!=null){
            apArticle.setChannelId(adChannel.getId());
            apArticle.setChannelName(adChannel.getName());
        }
        return articleFeign.saveArticle(apArticle);
    }

     //保存文章配置信息
    private void saveArticleConfig(ApArticle apArticle) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        apArticleConfig.setIsComment(true);
        apArticleConfig.setIsForward(true);
        apArticleConfig.setIsDown(false);
        apArticleConfig.setIsDelete(false);
        articleFeign.saveArticleConfig(apArticleConfig);
    }

    //保存文章内容
    private void saveArticleContent(ApArticle apArticle, WmNews wmNews) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());
        articleFeign.saveArticleContent(apArticleContent);
    }

    //修改自媒体新闻
    private void updateWmNews(WmNews wmNews, short status, String msg) {
         wmNews.setStatus(status);
         wmNews.setReason(msg);
         wemediaFeign.updateWmNews(wmNews);
    }
     @Autowired
     AdSensitiveMapper adSensitiveMapper;
    //处理自定义敏感词
    private boolean handleSensitive(WmNews wmNews, String text) {
        //查询出数据库中维护的敏感词列表
        List<String> allSensitive = adSensitiveMapper.findAllSensitive();
        //将敏感词列表封装成dfa需要的数据模型
        SensitiveWordUtil.initMap(allSensitive);
        log.info("敏感词列表加载完成==>{}",SensitiveWordUtil.dictionaryMap);
        //使用dfa进行敏感词过滤，再过滤结果中查看是否有敏感词
        Map<String, Integer> matchWords = SensitiveWordUtil.matchWords(text);
        if (matchWords!=null && matchWords.size()>0){
            updateWmNews(wmNews,(short)2,"文本中包含敏感词，审核失败");
            log.info("发现敏感词==>{}",matchWords);
            return false;
        }
        return true;
    }
    //阿里云图片审核
    @Autowired
    GreenImageScan greenImageScan;
    @Autowired
    FastDFSClient fastDFSClient;
    @Value("${fdfs.url}")
    String fileServerUrl;
    private boolean handleImagesScan(WmNews wmNews, List<String> images) {
        //传入的图片集合为路径集合需要转化byte{}集合
        List<byte[]> imagesByteList = new ArrayList<>();
        //
        for (String url : images) {
            //截取前缀
            String imgUrl = url.replace(fileServerUrl, "").trim();
            //获取"/"的下标
            int index = imgUrl.indexOf("/");
            //截取分组名和文件名
            String groupName = imgUrl.substring(0, index);
            String path = imgUrl.substring(index + 1);
      try {
        imagesByteList.add(fastDFSClient.download(groupName,path));
       }catch (IOException e){
          e.printStackTrace();
          log.error("fastdfs下载图片失败==> group={} path={}",groupName,path);
      }
        }
        try {
            Map map = greenImageScan.imageScan(imagesByteList);
            String suggest =(String) map.get(AuthConstants.AUTH_SUGGESTION);
            if(AuthConstants.AUTH_PASS.equals(suggest)){
                //审核通过
                return  true;
            }else if(AuthConstants.AUTH_REVIEW.equals(suggest)){
                updateWmNews(wmNews,(short)3,"图片中有不确定因素，需要进行人工审核");
            }else {
                updateWmNews(wmNews,(short)2,",\"图片中有违规，图片审核失败\"");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("调用阿里云图片检测服务失败==>{}",e.getMessage());
        }
        return false;
    }
//
//    public static void main(String[] args) {
//        String str= "group1/M00/00/00/wKjIgmAP3ZuAKo7CAAGCJEqK0S8471.jpg";
//        int index = str.indexOf("/");
//        String s1 = str.substring(0, index);
//        String s2 = str.substring(index+1);
//        System.out.println(s1);
//        System.out.println(s2);
//    }
     @Autowired
     GreeTextScan greenTextScan; //文本扫描
    private boolean handleTextScan(WmNews wmNews, String text) {
        try {
            Map map = greenTextScan.greeTextScan(text);
            //获取审核建议字段
            String suggest =(String)map.get(AuthConstants.AUTH_SUGGESTION);
            if(AuthConstants.AUTH_PASS.equals(suggest)){
                return true;
            }else if(AuthConstants.AUTH_REVIEW.equals(suggest)){
                //需要人工审核修改状态
                updateWmNews(wmNews,(short)3,"文章中有不确定因素，需要人工审核");
            }else {
                //修改为审核失败的状态
                updateWmNews(wmNews,(short)2,"文章中有违规信息，审核失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("\"阿里云文本审核出现异常, 当前审核新闻ID==>{}  异常原因==>{}\",wmNews.getId(),e.getMessage()");
        }
        return false;
    }
       //抽取文本内容及图片内容放入map
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //用于储存文本内容
        StringBuilder contentStr = new StringBuilder(wmNews.getTitle());
        //用于储存图片路径
        List<String> images = new ArrayList<>();
        List<Map> mapList = JSONArray.parseArray(wmNews.getContent(), Map.class);
        //遍历map
        for (Map map : mapList) {
            //拼接文本内容
            String type=(String) map.get("type");
          if ("text".equals(type)){
              contentStr.append(map.get("value"));
          }
          //添加图片
            if("images".equals(type)){
                images.add((String) map.get("value"));
            }
        }
        //添加封面图片
        String coverImages = wmNews.getImages();
        if(StringUtils.isNotBlank(contentStr)&&wmNews.getType()!=0){
            //因为封面字段使用 逗号拼接的图片列表需要split切割 得到图片数组
            images.addAll(Arrays.asList(coverImages.split(",")));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("text",contentStr.toString());
        map.put("images",contentStr.toString());
        return map;
    }
}
